home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Games of Daze
/
Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso
/
djgpp
/
go32
/
fs
/
perform.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-03-21
|
10KB
|
381 lines
#include <stdio.h>
#include <sys/types.h>
#include <dos.h>
#include <pc.h>
#include <go32.h>
#include <dpmi.h>
#define far
#include "ed.h"
#include "paging.h"
#include "perform.h"
#include "fsfuncts.h"
#define timer_channel 0x40 /* Timer channel (#0) of the timer chip */
#define command_reg 0x43 /* Command register of the timer chip */
#define ch_0_seq 0x36 /* 00110110 : ch 0, 2 bytes, mode 3, bin */
#define pulses_per_mili 1193 /* Number of pulses per call to New08() */
#define calls_per_tick 55 /* 65536/pulses_per_mili=calls per .055s */
#define dos_clock_limit 0x0000fffe /* 65535 */
extern Go32_Info_Block _go32_info_block;
typedef struct {
unsigned short limit;
unsigned short base_lo;
unsigned long base_hi;
} IDT_STRUCT;
typedef struct {
unsigned short offset_lo;
unsigned short selector;
unsigned short type;
unsigned short offset_hi;
} IDT_ENTRY;
typedef struct {
unsigned short segment_limit;
unsigned short base_00_15;
unsigned char base_16_23;
unsigned char dummy1;
unsigned char dummy2;
unsigned char base_24_31;
} GDT_ENTRY;
IDT_STRUCT idt, gdt;
EVAL_DATA_TABLE evaluation_data;
word32 total_hits_count = 0;
int total_segments = EVAL_SEGMENTS;
int timer_is_set = 0;
int evaluation_is_running = 0;
static _go32_dpmi_seginfo old_rm_isr;
static _go32_dpmi_registers old_isr_regs;
static _go32_dpmi_seginfo emu_rm_si;
static _go32_dpmi_registers emu_rm_regs;
static _go32_dpmi_seginfo emu_pm_si;
static _go32_dpmi_seginfo pm_si;
static IDT_ENTRY pm_old_idt_entry;
static union REGS regs;
volatile word32 dos_clock_tick = 0;
volatile word32 ebp, eip, esp;
static word32 segment_str_addr = 0, segment_stp_addr = 0, segment_len = 1;
static int ok_to_run = 0;
/* ---------------------------------------------------------------------- */
static void
get_idt_entry (int vectnum, IDT_ENTRY *idt_entry)
{
unsigned long idt_base, gdt_base;
int idt_index = vectnum & 0xff;
IDT_ENTRY *i_e;
asm("movl $_idt,%eax");
asm("sidt (%eax)");
asm("movl $_gdt,%eax");
asm("sgdt (%eax)");
if (idt_index >= 0x08 && idt_index <= 0x0f)
idt_index += _go32_info_block.master_interrupt_controller_base - 8;
else if (idt_index >= 0x70 && idt_index <= 0x77)
idt_index += _go32_info_block.slave_interrupt_controller_base - 0x70;
idt_base = (idt.base_hi << 16) + idt.base_lo + 0xe0000000;
gdt_base = (gdt.base_hi << 16) + gdt.base_lo + 0xe0000000;
i_e = (IDT_ENTRY *)(idt_base + 8 * idt_index);
if (i_e->selector > gdt.limit)
return;
idt_entry->offset_lo = i_e->offset_lo;
idt_entry->selector = i_e->selector;
idt_entry->type = i_e->type;
idt_entry->offset_hi = i_e->offset_hi;
}
/* ---------------------------------------------------------------------- */
static void
set_idt_entry (int vectnum, IDT_ENTRY *idt_entry)
{
unsigned long idt_base, gdt_base;
int idt_index = vectnum & 0xff;
IDT_ENTRY *i_e;
asm("movl $_idt,%eax");
asm("sidt (%eax)");
asm("movl $_gdt,%eax");
asm("sgdt (%eax)");
if (idt_index >= 0x08 && idt_index <= 0x0f)
idt_index += _go32_info_block.master_interrupt_controller_base - 8;
else if (idt_index >= 0x70 && idt_index <= 0x77)
idt_index += _go32_info_block.slave_interrupt_controller_base - 0x70;
idt_base = (idt.base_hi << 16) + idt.base_lo + 0xe0000000;
gdt_base = (gdt.base_hi << 16) + gdt.base_lo + 0xe0000000;
i_e = (IDT_ENTRY *)(idt_base + 8 * idt_index);
/* if (idt_entry->selector > gdt.limit)
return;
*/ /* Has to comment out because the original selector might not be. */
i_e->offset_lo = idt_entry->offset_lo;
i_e->selector = idt_entry->selector;
i_e->type = idt_entry->type;
i_e->offset_hi = idt_entry->offset_hi;
}
/* ---------------------------------------------------------------------- */
static void
analyze_eip (void)
{ if (eip <= segment_stp_addr && eip >= segment_str_addr)
{
eip -= segment_str_addr;
evaluation_data[eip / segment_len].hits_count++;
}
total_hits_count++;
}
/* ---------------------------------------------------------------------- */
static void
emulate_rm_isr_08 (void)
{
asm("cli");
asm("push %eax");
asm("push %edx");
asm("push %ds");
asm("push $0x48");
asm("pop %ds");
dos_clock_tick += pulses_per_mili;
asm("mov $0x20,%al");
asm("out %al,$0x20");
asm("pop %ds");
asm("pop %edx");
asm("pop %eax");
}
/* ---------------------------------------------------------------------- */
static void
emulate_pm_isr_08 (void)
{
asm("cli");
asm("push %eax");
asm("push %ebx");
asm("push %ecx");
asm("push %edx");
asm("push %ds");
asm("push $0x48");
asm("pop %ds");
dos_clock_tick += pulses_per_mili;
if (dos_clock_tick < dos_clock_limit)
{
asm("mov $0x20,%al");
asm("out %al,$0x20");
} else
{
asm("movl %ebp,_ebp");
asm("movl %esp,_esp");
old_isr_regs.x.cs = old_rm_isr.rm_segment;
old_isr_regs.x.ip = old_rm_isr.rm_offset;
old_isr_regs.x.ss = old_isr_regs.x.sp = 0;
regs.x.ax = 0x302;
regs.h.bh = 0;
regs.x.cx = 0;
regs.x.di = (unsigned long)(&old_isr_regs);
int86 (0x31, ®s, ®s);
asm("cli");
asm("movl _esp,%esp");
asm("movl _ebp,%ebp");
dos_clock_tick -= dos_clock_limit;
}
asm("pop %ds");
asm("pop %edx");
asm("pop %ecx");
asm("pop %ebx");
asm("pop %eax");
asm("leave");
asm("iret");
}
/* ---------------------------------------------------------------------- */
static void
my_pm_isr_08 (void)
{
asm("push %eax");
asm("push %ecx");
asm("push %edx");
asm("push %ds");
asm("push $0x48");
asm("pop %ds");
if (ok_to_run)
{
asm("movl %ebp,%eax");
asm("add $0x04,%eax");
asm("movl (%eax),%edx");
asm("movl %edx,_eip");
analyze_eip ();
}
asm("pop %ds");
asm("pop %edx");
asm("pop %ecx");
asm("pop %eax");
asm("leave");
asm("push %eax"); /* <=> db 50h */
asm("push %eax"); /* <=> db 50h */
asm("push %eax"); /* <=> db 50h */
asm("push %eax"); /* <=> db 50h */
asm("push %eax"); /* <=> db 50h */
asm("push %eax"); /* <=> db 50h */
asm("push %eax"); /* <=> db 50h */
}
/* ---------------------------------------------------------------------- */
int
set_timer ()
{
word32 old_selector, old_offset, jump_pos;
if (_go32_info_block.run_mode == _GO32_RUN_MODE_DPMI)
return (0);
if (!timer_is_set)
{
pm_si.pm_offset = (int) my_pm_isr_08;
pm_si.pm_selector = _go32_my_cs();
asm("cli");
get_idt_entry (8, &pm_old_idt_entry);
asm("sti");
jump_pos = (int) my_pm_isr_08 + 0x2b;
old_offset = ((unsigned long)pm_old_idt_entry.offset_hi << 16) |
(unsigned long)pm_old_idt_entry.offset_lo;
old_selector = (unsigned long)pm_old_idt_entry.selector;
if (old_offset)
{
write_child (jump_pos + 4, &old_selector, 2);
write_child (jump_pos , &old_offset, 4);
old_offset = 0xea; /* Opcode for intersegment jump */
write_child (jump_pos - 1, &old_offset, 1);
timer_is_set = 1;
}
else
{
int ret;
emu_rm_si.pm_offset = (int) emulate_rm_isr_08;
emu_pm_si.pm_offset = (int) emulate_pm_isr_08;
emu_pm_si.pm_selector = _go32_my_cs();
ret = _go32_dpmi_allocate_real_mode_callback_iret(
&emu_rm_si, &emu_rm_regs);
if (ret)
return 0;
disable();
_go32_dpmi_get_real_mode_interrupt_vector(8, &old_rm_isr);
_go32_dpmi_set_real_mode_interrupt_vector(8, &emu_rm_si);
_go32_dpmi_set_protected_mode_interrupt_vector(8, &emu_pm_si);
outportb (command_reg, ch_0_seq);
outportb (timer_channel, pulses_per_mili & 0xff);
outportb (timer_channel, pulses_per_mili >> 8);
enable();
old_offset = (unsigned long) emulate_pm_isr_08;
old_selector = _go32_my_cs ();
write_child (jump_pos + 4, &old_selector, 2);
write_child (jump_pos , &old_offset, 4);
old_offset = 0xea; /* Opcode for jump */
write_child (jump_pos - 1, &old_offset, 1);
timer_is_set = 2;
}
asm("cli");
_go32_dpmi_set_protected_mode_interrupt_vector(8, &pm_si);
asm("sti");
return 1;
}
return 0;
}
/* ---------------------------------------------------------------------- */
void
reset_timer ()
{
if (timer_is_set)
{
asm("cli");
set_idt_entry (8, &pm_old_idt_entry);
asm("sti");
if (timer_is_set == 2)
{
disable();
outportb (command_reg, ch_0_seq);
outportb (timer_channel, 0);
outportb (timer_channel, 0);
_go32_dpmi_set_real_mode_interrupt_vector(8, &old_rm_isr);
_go32_dpmi_free_real_mode_callback (&emu_rm_si);
enable();
}
timer_is_set = 0;
}
}
/* ---------------------------------------------------------------------- */
void
start_evaluate ()
{
if (timer_is_set)
{
evaluation_is_running = 1;
ok_to_run = 1;
}
}
/* ---------------------------------------------------------------------- */
void
stop_evaluate ()
{
ok_to_run = 0;
evaluation_is_running = 0;
}
/* ---------------------------------------------------------------------- */
void
init_eval_data (word32 start_addr, word32 stop_addr)
{
int i;
word32 real_str = start_addr, real_stp = stop_addr;
if ((!valid_addr (real_str, 1)) || (!valid_addr(real_stp - 1, 1)))
{ real_str = areas[A_text].first_addr;
real_stp = areas[A_text].last_addr;
}
segment_str_addr = real_str;
segment_stp_addr = real_stp;
segment_len = (real_stp - real_str) / EVAL_SEGMENTS;
if (segment_len <= 0)
segment_len = 1;
for (i = 0; i < EVAL_SEGMENTS; i++)
{
evaluation_data[i].start_addr = i * segment_len + real_str;
evaluation_data[i].stop_addr = (i + 1) * segment_len - 1 + real_str;
evaluation_data[i].hits_count = 0;
}
total_hits_count = 0;
}
/* ---------------------------------------------------------------------- */